home *** CD-ROM | disk | FTP | other *** search
- #include "vbc.h"
-
- struct IC *first_ic=0,*last_ic=0;
- int float_used;
-
- int do_arith(np,struct IC *,np,struct obj *);
-
- void add_IC(struct IC *new)
- /* fuegt ein IC ein */
- {
- int code;
- if(!new) return;
- if(nocode) {free(new);return;}
- new->next=0;
- new->q1.am=new->q2.am=new->z.am=0;
- code=new->code;
- if(code>=BEQ&&code<=BRA) new->q1.flags=new->q2.flags=new->z.flags=0;
- if(code==ALLOCREG||code==FREEREG||code==SAVEREGS||code==RESTOREREGS) new->typf=0;
- if(DEBUG&64) pric2(stdout,new);
- if(new->q1.flags&VAR){
- if(!new->q1.v) ierror(0);
- new->q1.v->flags|=USEDASSOURCE;
- if(code==ADDRESS||(new->q1.flags&VARADR)) new->q1.v->flags|=USEDASADR;
- new->q1.v->priority+=currentpri;
- }
- if(new->q2.flags&VAR){
- if(!new->q2.v) ierror(0);
- new->q2.v->flags|=USEDASSOURCE;
- if(code==ADDRESS||(new->q2.flags&VARADR)) new->q2.v->flags|=USEDASADR;
- new->q2.v->priority+=currentpri;
- }
- if(new->z.flags&VAR){
- if(!new->z.v) ierror(0);
- if(new->z.flags&DREFOBJ) new->z.v->flags|=USEDASSOURCE; else new->z.v->flags|=USEDASDEST;
- new->z.v->priority+=currentpri;
- }
- if(/*(c_flags_val[0].l&2)&&*/code==LABEL){
- /* entfernt Spruenge zu direkt folgenden Labels */
- struct IC *p=last_ic;
- while(p){
- if(p->typf==new->typf&&p->code>=BEQ&&p->code<=BRA){
- remove_IC(p);
- if(DEBUG&1) printf("%s l%d deleted\n",ename[p->code],p->typf);
- }else{
- if(p->code!=LABEL) break;
- }
- p=p->prev;
- }
- }
- if(last_ic){
- /* if(c_flags_val[0].l&2){*/
- if(code==ASSIGN){
- if((last_ic->z.flags&(REG|SCRATCH|DREFOBJ))==(REG|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.reg==new->q1.reg&&last_ic->code!=CALL){
- if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){
- if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
- /* verbindet op a,b->reg,move reg->c zu op a,b->c */
- /* hier fehlt aber noch Registerfreigabe */
- last_ic->z=new->z;
- if(DEBUG&1) printf("move and op combined\n");
- if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
- free_reg(new->q1.reg);
- free(new);
- return;
- }
- }
- }
- }
- if(last_ic->code==BRA){
- if(code!=LABEL&&code!=ALLOCREG&&code!=FREEREG){
- /* loescht alles nach bra bis ein Label kommt */
- /* momentan noch nicht perfekt, da es bei alloc/freereg stoppt */
- free(new);
- if(DEBUG&1) printf("Unreachable Statement deleted\n");
- return;
- }
- if(last_ic->prev&&code==LABEL){
- /* ersetzt bcc l1;bra l2;l1 durch b!cc l2 */
- if(last_ic->prev->code>=BEQ&&last_ic->prev->code<=BGT&&new->typf==last_ic->prev->typf){
- if(DEBUG&1) printf("%s l%d;%s l%d; substituted\n",ename[last_ic->prev->code],last_ic->prev->typf,ename[last_ic->code],last_ic->typf);
- if(last_ic->prev->code&1) last_ic->prev->code--;
- else last_ic->prev->code++;
- last_ic->prev->typf=last_ic->typf;
- last_ic=last_ic->prev;
- free(last_ic->next);
- last_ic->next=new;new->prev=last_ic;
- last_ic=new;
- return;
- }
- }
- }
- /* }*/
- new->prev=last_ic;
- last_ic->next=new;
- last_ic=new;
- }else{
- last_ic=new;first_ic=new;new->prev=0;
- }
- /* Merken, on Fliesskomma benutzt wurde */
- if(code!=LABEL&&(code<BEQ||code>BRA))
- if((new->typf&15)==FLOAT||(new->typf&15)==DOUBLE) float_used=1;
- if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
- free_reg(new->q1.reg);
- if((new->q2.flags&SCRATCH)&&(new->q2.reg!=new->z.reg||!(new->z.flags®)))
- free_reg(new->q2.reg);
- }
- void free_IC(struct IC *p)
- /* Gibt IC-Liste inkl. Typen frei */
- {
- struct IC *merk;
- while(p){
- if(!(c_flags_val[0].l&128)){
- if(p->q1.am||p->q2.am||p->z.am)
- {p->q1.am=p->q2.am=p->z.am=0;ierror(0);}
- }else{
- if(p->q1.am) free(p->q1.am);
- if(p->q2.am) free(p->q2.am);
- if(p->z.am) free(p->z.am);
- }
- merk=p->next;
- free(p);
- p=merk;
- }
- }
- void gen_IC(np p,int ltrue,int lfalse)
- /* Erzeugt eine IC-Liste aus einer expression */
- {
- struct IC *new;
- if(!p) return;
- if(p->flags==STRING){
- /* hier fehlt noch die Verwaltung der String-Inhalte */
- p->o.v=add_var(empty,clone_typ(p->ntyp),STATIC,(struct const_list *)p->identifier);
- p->o.v->flags|=DEFINED;
- p->o.flags=VAR;
- p->o.reg=0;
- p->o.val=p->val;
- return;
- }
- if(p->flags==IDENTIFIER){
- p->o.v=find_var(p->identifier,0);
- p->o.flags=VAR;
- p->o.reg=0;
- p->o.val=p->val;
- return;
- }
- if(p->flags==CEXPR||p->flags==PCEXPR){
- if(p->left){
- if(p->left->flags==POSTINC) p->left->flags=PREINC;
- if(p->left->flags==POSTDEC) p->left->flags=PREDEC;
- gen_IC(p->left,0,0);
- if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
- }
- if(p->right){
- if(p->right->flags==POSTINC) p->right->flags=PREINC;
- if(p->right->flags==POSTDEC) p->right->flags=PREDEC;
- gen_IC(p->right,0,0);
- if(p->right->o.flags&SCRATCH) free_reg(p->right->o.reg);
- }
- p->o.flags=KONST;
- p->o.val=p->val;
- p->o.reg=0;
- return;
- }
- if(p->flags==KOMMA){
- if(p->left->sidefx){
- gen_IC(p->left,0,0);
- if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
- } else error(129);
- gen_IC(p->right,0,0);
- p->o=p->right->o;
- return;
- }
- if(p->flags==CAST){
- gen_IC(p->left,0,0);
- convert(p->left,p->ntyp->flags&31);
- p->o=p->left->o;
- return;
- }
- if(p->flags==FIRSTELEMENT){
- gen_IC(p->left,0,0);
- p->o=p->left->o;
- return;
- }
- new=(struct IC *)mymalloc(ICS);
- new->typf=p->ntyp->flags&31;
- new->q1.reg=new->q2.reg=new->z.reg=0;
- new->q1.flags=new->q2.flags=new->z.flags=0;
- if((p->flags>=LSHIFT&&p->flags<=MOD)||(p->flags>=OR&&p->flags<=AND)||p->flags==PMULT){
- do_arith(p,new,0,0);
- return;
- }
- if(p->flags==CONTENT){
- gen_IC(p->left,0,0);
- if(p->left->o.flags&VARADR){
- free(new);
- p->o=p->left->o;
- p->o.flags&=~VARADR;
- return;
- }
- if(!(p->left->o.flags&DREFOBJ)){
- free(new);
- p->o=p->left->o;
- p->o.flags|=DREFOBJ;
- return;
- }
- if(p->left->o.flags&SCRATCH){
- new->z=p->left->o;
- new->z.flags&=~DREFOBJ;
- }else{
- /* hier muss man noch was aender, da das so nicht funktioniert */
- get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags);
- }
- new->code=ASSIGN;new->typf=POINTER;
- new->q1=p->left->o;
- new->q2.reg=sizetab[POINTER];
- add_IC(new);
- p->o=new->z;
- p->o.flags|=DREFOBJ;
- return;
- }
- if(p->flags==ASSIGN){
- new->code=ASSIGN;
- gen_IC(p->right,0,0);
- gen_IC(p->left,0,0);
- convert(p->right,p->ntyp->flags&31);
- new->q1=p->right->o;
- new->z=p->left->o;
- new->q2.reg=szof(p->left->ntyp);
- add_IC(new);
- p->o=new->z;
- return;
- }
- if(p->flags==ASSIGNADD){
- /* das hier ist nicht besonders schoen */
- struct obj o;struct IC *n;int f;
- if(p->right->right==0){
- /* sowas wie a+=0 wurde wegoptimiert */
- free(new);
- p->o=p->left->o;
- return;
- }
- f=do_arith(p->right,new,p->left,&o);
- if(!f) {ierror(0);return;}
- if(f>1) {ierror(0);return;}
- if(!nocode&&(o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&!regs[o.reg]){
- /* ueberfluessiges FREEREG entfernen */
- n=last_ic;
- while(n){
- if(n->code==FREEREG&&n->q1.reg==o.reg){
- remove_IC(n);if(!nocode) regs[o.reg]=1;
- break;
- }
- n=n->prev;
- }
- }
- convert(p->right,p->ntyp->flags&31);
- new=(struct IC *)mymalloc(ICS);
- new->typf=p->ntyp->flags&31;
- new->q2.flags=0;
- new->code=ASSIGN;
- new->q1=p->right->o;
- new->z=o;
- new->q2.reg=szof(p->left->ntyp);
- add_IC(new);
- p->o=new->z;
- return;
- }
- if(p->flags==MINUS||p->flags==KOMPLEMENT){
- new->code=p->flags;
- gen_IC(p->left,0,0);
- convert(p->left,p->ntyp->flags);
- if(regok(p->left->o.reg,p->ntyp->flags,0)&&(p->left->o.flags&SCRATCH)){
- new->z=p->left->o;
- new->z.flags&=~DREFOBJ;
- }else{
- get_scratch(&new->z,p->left->ntyp->flags,0);
- }
- new->q1=p->left->o;
- add_IC(new);
- p->o=new->z;
- return;
- }
- if(p->flags==ADDRESS||p->flags==ADDRESSA||p->flags==ADDRESSS){
- new->code=ADDRESS;
- new->typf=p->left->ntyp->flags&31;
- gen_IC(p->left,0,0);
- if(p->left->o.flags&VAR) p->left->o.v->flags|=USEDASSOURCE|USEDASDEST;
- if(p->left->o.flags&DREFOBJ){
- free(new);
- p->o=p->left->o;
- p->o.flags&=~DREFOBJ;
- return;
- }
- if((p->left->o.flags&VAR)&&!(p->left->o.flags&VARADR)
- &&(p->left->o.v->storage_class==EXTERN||p->left->o.v->storage_class==STATIC)){
- free(new);
- p->o=p->left->o;
- p->o.flags|=VARADR;
- return;
- }
- new->q1=p->left->o;
- get_scratch(&new->z,POINTER,p->ntyp->next->flags);
- add_IC(new);
- p->o=new->z;
- return;
- }
- if(p->flags==LAND||p->flags==LOR){
- int l1,l2,l3,l4;
- /* printf("%s true=%d false=%d\n",ename[p->flags],ltrue,lfalse);*/
- l1=++label;if(!ltrue) {l2=++label;l3=++label;l4=++label;}
- if(!ltrue){if(p->flags==LAND) gen_IC(p->left,l1,l3);
- else gen_IC(p->left,l3,l1);
- }else {if(p->flags==LAND) gen_IC(p->left,l1,lfalse);
- else gen_IC(p->left,ltrue,l1);
- }
- if(p->left->o.flags!=0){
- new->code=TEST;
- new->q2.flags=new->z.flags=0;
- new->typf=p->left->ntyp->flags&31;
- new->q1=p->left->o;
- add_IC(new);
- new=(struct IC *)mymalloc(ICS);
- if(p->flags==LAND) new->code=BEQ; else new->code=BNE;
- if(!ltrue) new->typf=l3;
- else{if(p->flags==LAND) new->typf=lfalse; else new->typf=ltrue;}
- add_IC(new);
- }
- gen_label(l1);
- if(!ltrue){if(p->flags==LAND) gen_IC(p->right,l2,l3);
- else gen_IC(p->right,l3,l2);
- }else gen_IC(p->right,ltrue,lfalse);
- if(p->right->o.flags!=0){
- new=(struct IC *)mymalloc(ICS);
- new->code=TEST;
- new->q2.flags=new->z.flags=0;
- new->typf=p->right->ntyp->flags&31;
- new->q1=p->right->o;
- add_IC(new);
- new=(struct IC *)mymalloc(ICS);
- if(p->flags==LAND) new->code=BEQ; else new->code=BNE;
- if(!ltrue) new->typf=l3;
- else{if(p->flags==LAND) new->typf=lfalse; else new->typf=ltrue;}
- add_IC(new);
- }
- if(!ltrue){
- gen_label(l2);
- if(p->flags==LAND) p->o=gen_cond(0,l3,l4); else p->o=gen_cond(1,l3,l4);
- }else{
- new=(struct IC *)mymalloc(ICS);
- new->code=BRA;
- if(p->flags==LAND) new->typf=ltrue; else new->typf=lfalse;
- add_IC(new);
- }
- if(ltrue) p->o.flags=0;
- return;
- }
- if(p->flags==NEGATION){
- int l1,l2,l3;
- if(!ltrue) {l1=++label;l2=++label;l3=++label;}
- if(ltrue) gen_IC(p->left,lfalse,ltrue); else gen_IC(p->left,l1,l3);
- if(!p->left->o.flags) {free(new);p->o.flags=0;
- }else{
- new->code=TEST;
- new->q2.flags=new->z.flags=0;
- new->typf=p->left->ntyp->flags&31;
- new->q1=p->left->o;
- add_IC(new);
- new=(struct IC *)mymalloc(ICS);
- new->code=BNE;
- if(!ltrue) new->typf=l1; else new->typf=lfalse;
- add_IC(new);
- }
- if(ltrue){
- new=(struct IC *)mymalloc(ICS);
- new->code=BRA;
- if(!ltrue) new->typf=l2; else new->typf=ltrue;
- add_IC(new);
- p->o.flags=0;
- }else{
- gen_label(l3);
- p->o=gen_cond(0,l1,l2);
- }
- return;
- }
- if(p->flags>=EQUAL&&p->flags<=GREATEREQ){
- int l1,l2,l3,tl,tr,swapped;
- if(!ltrue) {l1=++label;l2=++label;l3=++label;}
- if(p->left->flags==CEXPR){
- /* Konstanten nach rechts */
- np merk;merk=p->left;p->left=p->right;p->right=merk;
- swapped=1;
- }else swapped=0;
- new->code=COMPARE;
- tl=p->left->ntyp->flags&31;tr=p->right->ntyp->flags&31;
- if(p->right->flags==CEXPR&&(tr&15)<FLOAT&&(tl&15)<FLOAT){
- zlong null;int negativ;
- eval_constn(p->right);
- null=l2zl(0L);
- if(zlleq(vlong,0)) negativ=1; else negativ=0;
- if(tr&UNSIGNED) negativ=0;
- if((!negativ||zlleq(t_min[tl],vlong))&&(negativ||zulleq(vulong,t_max[tl]))){
- convert(p->right,tl);
- tr=tl;
- }
- }
- if(arith(tl)&&tl!=tr){
- struct Typ *t;
- t=arith_typ(p->left->ntyp,p->right->ntyp);
- new->typf=t->flags&31;
- freetyp(t);
- }else{
- new->typf=p->left->ntyp->flags&31;
- }
- gen_IC(p->left,0,0);
- convert(p->left,new->typf);
- gen_IC(p->right,0,0);
- convert(p->right,new->typf);
- new->q1=p->left->o;
- new->q2=p->right->o;
- new->z.flags=0;
- add_IC(new);
- new=(struct IC *)mymalloc(ICS);
- if(p->flags==EQUAL) new->code=BEQ;
- if(p->flags==INEQUAL) new->code=BNE;
- if(p->flags==LESS) {if(swapped) new->code =BGT; else new->code=BLT;}
- if(p->flags==LESSEQ){if(swapped) new->code=BGE; else new->code=BLE;}
- if(p->flags==GREATER){if(swapped) new->code=BLT; else new->code=BGT;}
- if(p->flags==GREATEREQ){if(swapped) new->code=BLE; else new->code=BGE;}
- if(ltrue) new->typf=ltrue; else new->typf=l1;
- add_IC(new);
- if(ltrue){
- new=(struct IC *)mymalloc(ICS);
- new->code=BRA;
- new->typf=lfalse;
- add_IC(new);
- p->o.flags=0;
- }else{
- gen_label(l3);
- p->o=gen_cond(1,l1,l2);
- }
- return;
- }
- if(p->flags==CALL){
- int r,regused,sz;
- function_calls+=currentpri;
- gen_IC(p->left,0,0);
- if(!(p->left->o.flags&DREFOBJ)){
- free(new);
- p->o=p->left->o;
- if(p->o.flags&VARADR) p->o.flags&=~VARADR;
- else p->o.flags|=DREFOBJ;
- }else{
- if(p->left->o.flags&VARADR){
- free(new);
- p->o=p->left->o;
- p->o.flags&=~VARADR;
- }else{
- if(p->left->o.flags&SCRATCH){
- new->z=p->left->o;
- new->z.flags&=~DREFOBJ;
- }else{
- /* das hier funktioniert vermutlich auch nicht */
- get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags);
- }
- new->code=ASSIGN;new->typf=POINTER;
- new->q1=p->left->o;
- new->q2.reg=sizetab[POINTER];
- new->q2.flags=0;
- add_IC(new);
- p->o=new->z;
- p->o.flags|=DREFOBJ;
- }
- }
- /* p->left->o.flags-=DREFOBJ|VARADR; Was sollte das?? */
- r=freturn(p->ntyp);
- if(!r){
- struct Typ *t=mymalloc(TYPS);
- t->flags=POINTER;t->next=p->ntyp;
- r=freturn(t);
- free(t);
- }
- if(!r) ierror(0);
- regused=regs[r];
- new=(struct IC *)mymalloc(ICS);
- new->code=SAVEREGS;
- new->typf=0;
- if((p->o.flags&(REG|SCRATCH))==(REG|SCRATCH)) new->q1.reg=p->o.reg;
- else new->q1.reg=0;
- new->q1.flags=new->q2.flags=new->z.flags=0;
- add_IC(new);
- sz=push_args(p->alist,p->left->ntyp->next->exact,0);
- if(!regused){
- if(!nocode) regs[r]=1;
- new=(struct IC *)mymalloc(ICS);
- new->code=ALLOCREG;
- new->typf=0;
- new->q1.flags=REG;
- new->q1.reg=r;
- new->q2.flags=new->z.flags=0;
- add_IC(new);regused=0;
- }
- new=(struct IC *)mymalloc(ICS);
- new->code=CALL;new->typf=FUNKT;
- new->q1=p->o;new->q2.flags=0;
- new->q2.reg=sz;
- new->z.reg=r;
- /* hier noch Returnregister retten etc. */
- new->z.flags=REG;
- if(!regused) new->z.flags|=SCRATCH;
- add_IC(new);
- p->o=new->z;
- if(!freturn(p->ntyp)) p->o.flags|=DREFOBJ;
- if(regused){
- if((p->ntyp->flags&15)!=VOID){
- new=(struct IC *)mymalloc(ICS);
- new->code=ASSIGN;
- new->typf=p->ntyp->flags&31;
- new->q1=p->o;
- new->q2.reg=szof(p->ntyp);
- new->q2.flags=0;
- get_scratch(&new->z,p->ntyp->flags&31,0);
- add_IC(new);
- p->o=new->z;
- }
- }
- new=(struct IC *)mymalloc(ICS);
- new->code=RESTOREREGS;
- new->typf=0;
- if(p->o.flags®) new->q1.reg=p->o.reg; else new->q1.reg=0;
- new->q1.flags=new->q2.flags=new->z.flags=0;
- add_IC(new);
- return;
- }
- if(p->flags>=PREINC&&p->flags<=POSTDEC){
- struct obj o;
- gen_IC(p->left,0,0);
- if(p->flags==POSTINC||p->flags==POSTDEC){
- new=(struct IC *)mymalloc(ICS);
- new->code=ASSIGN;
- new->typf=p->ntyp->flags&31;
- new->q2.reg=sizetab[p->ntyp->flags&15];
- new->q1=p->left->o;
- new->q1.flags&=~SCRATCH;
- get_scratch(&new->z,p->left->ntyp->flags&31,0);
- new->q2.flags=0;
- add_IC(new);
- o=new->z;
- new=(struct IC *)mymalloc(ICS);
- }else o=p->left->o;
- if((p->left->ntyp->flags&15)==POINTER){
- if(p->flags==PREINC||p->flags==POSTINC) new->code=ADDI2P; else new->code=SUBIFP;
- vlong=l2zl((long)szof(p->left->ntyp->next));
- new->q2.val.vint=zl2zi(vlong);
- new->typf=INT;
- new->q1=p->left->o;
- new->z=p->left->o;
- new->q2.flags=KONST;
- add_IC(new);
- }else{
- if(p->flags==PREINC||p->flags==POSTINC) new->code=ADD; else new->code=SUB;
- new->typf=p->ntyp->flags&31;
- new->q1=p->left->o;
- new->z=p->left->o;
- new->q2.flags=KONST;
- vlong=l2zl(1L);vulong=zl2zul(vlong);vdouble=zl2zd(vlong);
- if(new->typf==CHAR) new->q2.val.vchar=zl2zc(vlong);
- if(new->typf==SHORT) new->q2.val.vshort=zl2zs(vlong);
- if(new->typf==INT) new->q2.val.vint=zl2zi(vlong);
- if(new->typf==LONG) new->q2.val.vlong=vlong;
- if(new->typf==(UNSIGNED|CHAR)) new->q2.val.vuchar=zul2zuc(vulong);
- if(new->typf==(UNSIGNED|SHORT)) new->q2.val.vushort=zul2zus(vulong);
- if(new->typf==(UNSIGNED|INT)) new->q2.val.vuint=zul2zui(vulong);
- if(new->typf==(UNSIGNED|LONG)) new->q2.val.vulong=vulong;
- if(new->typf==DOUBLE) new->q2.val.vdouble=vdouble;
- if(new->typf==FLOAT) new->q2.val.vfloat=zd2zf(vdouble);
- add_IC(new);
- }
- if(p->flags==POSTINC||p->flags==POSTDEC){
- if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
- }
- p->o=o;
- return;
- }
- if(p->flags==COND){
- int ltrue,lfalse,lout;
- ltrue=++label;lfalse=++label;lout=++label;
- gen_IC(p->left,ltrue,lfalse);
- if(!p->left->o.flags){
- free(new);
- }else{
- if(p->left->flags!=CEXPR){
- new->code=TEST;
- new->typf=p->left->ntyp->flags&31;
- new->q1=p->left->o;
- new->q2.flags=new->z.flags=0;
- add_IC(new);
- new=(struct IC *)mymalloc(ICS);
- new->code=BEQ;
- new->typf=lfalse;
- add_IC(new);
- }else{
- eval_constn(p->left);
- if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)){
- gen_IC(p->right->right,0,0);
- p->o=p->right->right->o;
- }else{
- gen_IC(p->right->left,0,0);
- p->o=p->right->left->o;
- }
- return;
- }
- }
- gen_label(ltrue);
- gen_IC(p->right->left,0,0);
- convert(p->right->left,p->ntyp->flags&31);
- if(p->right->left->o.flags&SCRATCH){
- p->o=p->right->left->o;
- }else{
- get_scratch(&p->o,p->ntyp->flags&31,0);
- new=(struct IC *)mymalloc(ICS);
- new->code=ASSIGN;
- new->q1=p->right->left->o;
- new->z=p->o;
- new->q2.flags=0;
- new->q2.reg=szof(p->ntyp);
- new->typf=p->ntyp->flags&31;
- add_IC(new);
- p->o=new->z;
- }
- new=(struct IC *)mymalloc(ICS);
- new->code=BRA;
- new->typf=lout;
- add_IC(new);
- gen_label(lfalse);
- gen_IC(p->right->right,0,0);
- convert(p->right->right,p->ntyp->flags&31);
- new=(struct IC *)mymalloc(ICS);
- new->code=ASSIGN;
- new->q1=p->right->right->o;
- new->z=p->o;
- new->q2.flags=0;
- new->q2.reg=szof(p->ntyp);
- new->typf=p->ntyp->flags&31;
- add_IC(new);
- gen_label(lout);
- return;
- }
- printf("Operation: %d=%s\n",p->flags,ename[p->flags]);
- ierror(0);
- free(new);
- p->o.flags=0;
- }
- int push_args(struct argument_list *al,struct struct_declaration *sd,int n)
- /* Legt die Argumente eines Funktionsaufrufs in umgekehrter Reihenfolge */
- /* auf den Stack. Es wird Integer-Erweiterung vorgenommen und float wird */
- /* nach double konvertiert, falls kein Prototype da ist. Ausserdem werden */
- /* alle Argumente in ihrer Groesse aligned. Das ist evtl. nicht fuer jede */
- /* CPU ausreichend. Hier muss evtl. noch etwas getan werden. */
- {
- int of,t,sz;struct IC *new;
- if(!al) return(0);
- if(al->next) of=push_args(al->next,sd,n+1); else of=0;
- if(!al->arg) {ierror(0);return(of);}
- if(!sd) {ierror(0);return(of);}
- gen_IC(al->arg,0,0);
- if(n<sd->count){t=sd->sl[n].styp->flags&15;sz=szof(sd->sl[n].styp);}
- else {t=al->arg->ntyp->flags&15;sz=szof(al->arg->ntyp);}
- if(t>=CHAR&&t<=LONG) {t=int_erw(t);sz=sizetab[t&15];}
- if(t==FLOAT&&n>=sd->count) {t=DOUBLE;sz=sizetab[t];}
- convert(al->arg,t&31);
- new=(struct IC *)mymalloc(ICS);
- new->code=PUSH;
- new->typf=t;
- new->q1=al->arg->o;
- new->q2.flags=new->z.flags=0;
- new->q2.reg=((sz+maxalign-1)/maxalign)*maxalign;
- add_IC(new);
- return(of+sz);
- }
-
- void convert(np p,int f)
- /* konvertiert das Objekt in p->o in bestimmten Typ */
- {
- struct IC *new;
- if((f&15)==VOID||(p->ntyp->flags&31)==f) return;
- if(p->flags==CEXPR||p->flags==PCEXPR){
- eval_constn(p);
- p->ntyp->flags=f;
- insert_const(p);
- p->o.val=p->val;
- return;
- }
- if(!must_convert(p,f)) return;
- new=(struct IC *)mymalloc(ICS);
- new->q1=p->o;
- new->q2.flags=0;
- new->code=CONVCHAR+(p->ntyp->flags&15)-CHAR;
- if(p->ntyp->flags&UNSIGNED) new->code+=8;
- new->typf=f;
- if(!regok(p->o.reg,f,0)||!(p->o.flags&SCRATCH)){
- get_scratch(&new->z,f,0);
- add_IC(new);
- }else{
- new->z=p->o;new->z.flags&=~DREFOBJ;
- add_IC(new);
- }
- p->o=new->z;
- }
-
- int allocreg(int f,int mode)
- /* Fordert Register fuer Typ f an */
- /* evtl. maschinenabhaengig, aber hier fehlt noch viel */
- /* z.B. Eintragen eines IC */
- {
- int i;struct IC *new;
- if(nocode) return(1);
- for(i=1;i<=MAXR;i++){
- if(!regs[i]&®ok(i,f,mode)){
- if(DEBUG&16) printf("alocated %s\n",regnames[i]);
- regs[i]=1;regused[i]++;
- new=(struct IC *)mymalloc(ICS);
- new->code=ALLOCREG;
- new->typf=0;
- new->q1.flags=REG;
- new->q1.reg=i;
- new->q2.flags=new->z.flags=0;
- add_IC(new);
- return(i);}
- }
- if(DEBUG&1) printf(">%sCouldn't allocate register for type %d\n",string,f);
- return(0);
- }
- void free_reg(int r)
- /* Gibt Register r frei */
- /* Eintrag eines IC fehlt noch */
- {
- struct IC *new;
- if(!r||nocode) return;
- if(regs[r]==0) {printf("Register %s:\n",regnames[r]);ierror(0);}
- if(DEBUG&16) printf("freed %s\n",regnames[r]);
- new=(struct IC *)mymalloc(ICS);
- new->code=FREEREG;
- new->typf=0;
- new->q1.flags=REG;
- new->q1.reg=r;
- new->q2.flags=new->z.flags=0;
- add_IC(new);
- regs[r]=0;
- }
- void gen_label(int l)
- /* Erzeugt ein Label */
- {
- struct IC *new;
- new=(struct IC *)mymalloc(ICS);
- new->code=LABEL;
- new->typf=l;
- new->q1.flags=new->q2.flags=new->z.flags=0;
- add_IC(new);
- }
- struct obj gen_cond(int m,int l1,int l2)
- /* Generiert code, der 0 oder 1 in Register schreibt */
- {
- struct IC *new;
- struct obj omerk;
- new=(struct IC *)mymalloc(ICS);
- new->code=ASSIGN;
- new->typf=INT;
- new->q1.flags=KONST;
- new->q2.flags=0;
- new->q2.reg=sizetab[INT];
- if(!m) vlong=l2zl(1L); else vlong=l2zl(0L);
- new->q1.val.vint=zl2zi(vlong);
- get_scratch(&new->z,INT,0);
- omerk=new->z;
- add_IC(new);
- new=(struct IC *)mymalloc(ICS);
- new->code=BRA;
- new->typf=l2;
- add_IC(new);
- gen_label(l1);
- new=(struct IC *)mymalloc(ICS);
- new->code=ASSIGN;
- new->typf=INT;
- new->q1.flags=KONST;
- new->q2.flags=0;
- new->q2.reg=sizetab[INT];
- if(!m) vlong=l2zl(0L); else vlong=l2zl(1L);
- new->q1.val.vint=zl2zi(vlong);
- new->z=omerk;
- /* new->z.reg=r;
- new->z.flags=SCRATCH|REG;*/
- add_IC(new);
- gen_label(l2);
- return(omerk);
- }
- void scratch_var(struct obj *o,int t)
- /* liefert eine temporaere Variable */
- /* nicht effizient, aber wer hat schon so wenig Register... */
- {
- struct Typ *nt=(struct Typ *)mymalloc(TYPS);
- if((t&15)<CHAR||(t&15)>POINTER) ierror(0);
- nt->flags=t&31;
- if((t&15)==POINTER){
- nt->next=(struct Typ *)mymalloc(TYPS);
- nt->next->flags=VOID;
- nt->next->next=0;
- }else nt->next=0;
- o->flags=SCRATCH|VAR;o->reg=0;
- o->v=add_var(empty,nt,AUTO,0);
- o->val.vlong=l2zl(0L);
- }
- void get_scratch(struct obj *o,int t1,int t2)
- /* liefert ein Scratchregister oder eine Scratchvariable */
- {
- if(o->reg=allocreg(t1,t2)){
- o->flags=SCRATCH|REG;
- }else{
- scratch_var(o,t1);
- }
- }
- void remove_IC(struct IC *p)
- /* entfernt IC p aus Liste */
- {
- if(p->prev) p->prev->next=p->next; else first_ic=p->next;
- if(p->next) p->next->prev=p->prev; else last_ic=p->prev;
- if(p->q1.am) free(p->q1.am);
- if(p->q2.am) free(p->q2.am);
- if(p->z.am) free(p->z.am);
- free(p);
- }
- int do_arith(np p,struct IC *new,np dest,struct obj *o)
- /* erzeugt IC new fuer einen arithmetischen Knoten und speichert das */
- /* Resultat vom Unterknoten dest in o (fuer a op= b) */
- /* liefert 0, wenn dest nicht gefunden */
- {
- int f=0;
- new->code=p->flags;
- if(new->code==PMULT) new->code=MULT;
- gen_IC(p->left,0,0);
- if(dest&&p->left==dest) {*o=p->left->o;f++;}
- gen_IC(p->right,0,0);
- if(dest&&p->right==dest) {*o=p->right->o;f++;}
-
- if((p->left->ntyp->flags&15)==POINTER&&(p->right->ntyp->flags&15)==POINTER){
- /* Subtrahieren zweier Pointer */
- if(p->flags!=SUB) ierror(0);
- new->typf=INT;
- new->code=SUBPFP;
- new->q1=p->left->o;
- new->q2=p->right->o;
- if(p->left->o.flags&SCRATCH&®ok(p->left->o.reg,INT,0)){
- new->z=p->left->o;
- new->z.flags&=~DREFOBJ;
- }else{
- if(USEQ2ASZ&&(p->right->o.flags&SCRATCH)&®ok(p->right->o.reg,INT,0)){
- new->z=p->left->o;
- new->z.flags&=(~DREFOBJ);
- }else{
- get_scratch(&new->z,INT,0);
- }
- }
- add_IC(new);
- p->o=new->z;
- if(szof(p->left->ntyp->next)>1){
- new=(struct IC *)mymalloc(ICS);
- new->code=DIV;
- new->q1=p->o;
- new->q2.flags=KONST;
- vlong=l2zl((long)szof(p->left->ntyp->next));
- vint=zl2zi(vlong);
- new->q2.val.vint=vint;
- new->z=p->o;
- new->typf=INT;
- add_IC(new);
- }
- return(f);
- }
- if((p->flags==ADD||p->flags==SUB)&&(p->ntyp->flags&15)==POINTER){
- /* Addieren und Subtrahieren eines Integers zu einem Pointer */
- if(p->flags==ADD) new->code=ADDI2P; else new->code=SUBIFP;
- new->typf=p->right->ntyp->flags&31;
- new->q1=p->left->o;
- /* kleinere Typen als MINADDI2P erst in diesen wandeln */
- if((new->typf&15)<MINADDI2P){convert(p->right,/*UNSIGNED|*/MINADDI2P);new->typf=/*UNSIGNED|*/MINADDI2P;}
- new->q2=p->right->o;
- if((p->left->o.flags&SCRATCH)&®ok(new->q1.reg,POINTER,p->left->ntyp->next->flags&31)){
- new->z=p->left->o;
- new->z.flags&=(~DREFOBJ);
- }else{
- get_scratch(&new->z,POINTER,p->left->ntyp->next->flags&31);
- }
- add_IC(new);
- p->o=new->z;
- return(f);
- }
- convert(p->left,p->ntyp->flags&31);
- convert(p->right,p->ntyp->flags&31);
- new->q1=p->left->o;
- new->q2=p->right->o;
- new->typf=p->ntyp->flags&31;
- if((new->q1.flags&SCRATCH)&®ok(new->q1.reg,p->ntyp->flags,0)){
- new->z=new->q1;
- new->z.flags&=~DREFOBJ;
- }else{
- if((new->q2.flags&SCRATCH)&®ok(new->q2.reg,p->ntyp->flags,0)){
- if((p->flags>=OR&&p->flags<=AND)||p->flags==ADD||p->flags==MULT||p->flags==PMULT){
- /* bei kommutativen Operatoren vertauschen */
- new->z=new->q2;
- new->q2=new->q1;
- new->q1=new->z;
- new->z.flags&=~DREFOBJ;
- }else{
- if(USEQ2ASZ){
- new->z=new->q2;
- new->z.flags&=~DREFOBJ;
- }else{
- get_scratch(&new->z,new->typf,0);
- }
- }
- }else{
- get_scratch(&new->z,new->typf,0);
- }
- }
- add_IC(new);
- p->o=new->z;
- return(f);
- }
-